package com.szakul.pdf.controller;

import java.util.List;

import org.apache.log4j.Logger;

import com.szakul.pdf.Viewer;
import com.szakul.pdf.gui.InfoLayout;
import com.szakul.pdf.model.TreePageModel;
import com.szakul.pdf.model.ViewModel;
import com.szakul.pdf.model.Zoom;
import com.szakul.pdf.validators.PagesValidator;
import com.szakul.pdf.viewer.dao.beans.Leaf;
import com.szakul.pdf.viewer.dao.beans.Node;
import com.vaadin.data.Item;

import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.event.Action;
import com.vaadin.event.ItemClickEvent;
import com.vaadin.event.ItemClickEvent.ItemClickListener;

import com.vaadin.ui.Tree;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;

public class ViewController {

	private static final Logger LOGGER = Logger.getLogger(ViewController.class);

	private static final Action ACTION_ADD = new Action("Add child item");
	private static final Action ACTION_DELETE = new Action("Delete");
	private static final Action[] ACTIONS = new Action[] { ACTION_ADD,
			ACTION_DELETE };
	private static final Action[] ACTION_LEAF = new Action[] { ACTION_DELETE };
	private static final Action[] ACTION_ROOT = new Action[] { ACTION_ADD };
	private Viewer view;
	private ViewModel model;

	private int currentPage = 1;
	private String currentFileName = null;
	private Zoom currentZoom = Zoom.ZOOM_100;
	private List<Integer> serched;
	private String searchText = null;
	private int searchIterator;
	private PagesValidator validator;

	public ViewController(Viewer view, ViewModel model) {
		super();
		this.view = view;
		this.model = model;

		validator = new PagesValidator("");
		view.getPages().addValidator(validator);

		view.addTreeListener(new TreeItemClickListener());

		view.addUpButtonListener(new UpButtonListener());
		view.addDownButtonListener(new DownButtonListener());
		view.addZoomInButtonListener(new ZoomInListener());
		view.addZoomOutButtonListener(new ZoomOutListener());
		view.addSearchButtonListener(new SearchButtonListener());
		view.addPageListener(new PagesListener());
		view.addSearchNextButtonListener(new SearchNextButtonListener());
		view.addSearchPrevButtonListener(new SearchPrevtButtonListener());
		view.addTreeActionListener(new TreeActionListener(view.getTree()));
		view.addInfoPanelEditButtonListener(new InfoPanelEditButtonListener());

	}

	public void initData() {

		view.getTree().removeAllItems();
		model.setTree(view.getTree());
	}

	private class SearchNextButtonListener implements ClickListener {

		public void buttonClick(ClickEvent event) {

			if (currentFileName != null && searchText != null) {

				if (serched.size() > 0 && !searchText.isEmpty()) {

					if (searchIterator >= serched.size()) {
						searchIterator = 0;
					}

					currentPage = serched.get(searchIterator);

					currentZoom = Zoom.ZOOM_100;
					view.displayPdf(model.goPageSearch(currentPage,
									searchText));
					view.getPages().setValue(currentPage);
					view.getAllPages().setCaption("/" + model.getAllPages());
					view.displayMessage("Znaleziono. Ide do strony: "
							+ (currentPage));
					view.getZoomLabel().setCaption(currentZoom.toString());

					searchIterator++;

				}

			}
		}

	}

	private class SearchPrevtButtonListener implements ClickListener {

		public void buttonClick(ClickEvent event) {

			if (currentFileName != null && searchText != null) {

				if (serched.size() > 0 && !searchText.isEmpty()) {

					if (searchIterator < 0) {
						searchIterator = serched.size() - 1;
					}

					currentPage = serched.get(searchIterator);

					System.out.println(" currentPage " + currentPage);

					currentZoom = Zoom.ZOOM_100;
					view
							.displayPdf(model.goPageSearch(currentPage,
									searchText));
					view.getPages().setValue(currentPage);
					view.displayMessage("Znaleziono. Ide do strony: "
							+ (currentPage));
					view.getZoomLabel().setCaption(currentZoom.toString());

					searchIterator--;

					view
							.displayPdf(model.goPageSearch(currentPage,
									searchText));
				}

			}
		}

	}

	private class PagesListener implements ValueChangeListener {

		public void valueChange(ValueChangeEvent event) {

			int allPages = model.getAllPages();
			LOGGER.debug("PagesListener value Get all pages " + allPages);

			validator.setErrorMessage("Od 1 do " + allPages);
			validator.setRange(allPages);

			if (view.getPages().isValid()) {

				if (currentFileName != null) {

					if (view.getPages().getValue() instanceof Integer) {
						currentPage = (Integer) view.getPages().getValue();
					} else {
						currentPage = Integer.valueOf((String) view.getPages()
								.getValue());
					}

					currentZoom = Zoom.ZOOM_100;
					view.displayPdf(model.goPage(currentPage));
					view.getPages().setValue(currentPage);
					view.getZoomLabel().setCaption(currentZoom.toString());

				}

			}

		}

	}

	private class SearchButtonListener implements ClickListener {

		public void buttonClick(ClickEvent event) {

			if (!view.getSearchText().getValue().toString().isEmpty()) {

				searchText = view.getSearchText().getValue().toString();

				if (currentFileName != null) {
					serched = model.getSearchPages(searchText);

					if (serched.size() > 0) {

						view.addSearchContent(serched);
						currentPage = serched.get(0);

						System.out.println(" currentPage " + currentPage);

						currentZoom = Zoom.ZOOM_100;
						view.displayPdf(model.goPageSearch(currentPage,
								searchText));
						view.getPages().setValue(currentPage);
						view.displayMessage("Znaleziono. Ide do strony: "
								+ (currentPage));
						view.getZoomLabel().setCaption(currentZoom.toString());

						view.displayPdf(model.goPageSearch(currentPage,
								searchText));

					} else {
						view.displayMessage("Nie znaleziono !");
					}

				}

			}

		}

	}

	private class UpButtonListener implements ClickListener {

		public void buttonClick(ClickEvent event) {

			if (currentFileName != null) {

				if (currentPage < model.getAllPages()) {
					currentPage++;
					currentZoom = Zoom.ZOOM_100;
					view.displayPdf(model.goPage(currentPage));
					view.getPages().setValue(currentPage);
					view.getZoomLabel().setCaption(currentZoom.toString());
				}

			}
		}

	}

	private class DownButtonListener implements ClickListener {

		public void buttonClick(ClickEvent event) {

			if (currentFileName != null) {
				if (currentPage > 1) {
					currentPage--;
					currentZoom = Zoom.ZOOM_100;
					view.displayPdf(model.goPage(currentPage));
					view.getPages().setValue(currentPage);
					view.getZoomLabel().setCaption(currentZoom.toString());
				}
			}
		}

	}

	private class ZoomInListener implements ClickListener {

		public void buttonClick(ClickEvent event) {

			if (currentFileName != null) {
				if (currentZoom.ordinal() < Zoom.ZOOM_150.ordinal()) {
					currentZoom = Zoom.values()[currentZoom.ordinal() + 1];

					view.displayPdf(model.zoomPage(currentZoom));

				}

				view.getZoomLabel().setCaption(currentZoom.toString());
			}

		}

	}

	private class ZoomOutListener implements ClickListener {

		public void buttonClick(ClickEvent event) {

			if (currentFileName != null) {

				if (currentZoom.ordinal() > Zoom.ZOOM_50.ordinal()) {
					currentZoom = Zoom.values()[currentZoom.ordinal() - 1];
					// view.displayPdf(model.createPage(currentFileName
					// ,currentZoom, currentPage));
					view.displayPdf(model.zoomPage(currentZoom));

				}
				view.getZoomLabel().setCaption(currentZoom.toString());
			}
		}

	}

	private class TreeActionListener implements Action.Handler {

		private Tree tree;

		public TreeActionListener(Tree tree) {
			this.tree = tree;
		}

		public Action[] getActions(Object target, Object sender) {

			if (target != null) {
				Object targetObject = tree.getContainerProperty(target,
						TreePageModel.TREE_PAGE_MODEL).getValue();

				if (targetObject instanceof Node) {
					return ACTIONS;
				} else if (targetObject instanceof String) {
					return ACTION_ROOT;
				}
			}

			return ACTION_LEAF;
		}

		public void handleAction(Action action, Object sender, Object target) {

			if (action == ACTION_ADD && target != null) {
				// Allow children for the target item, and expand it

				Object targetObject = tree.getContainerProperty(target,
						TreePageModel.TREE_PAGE_MODEL).getValue();

				if (targetObject instanceof Node) {

					Node node = (Node) targetObject;
					tree.setChildrenAllowed(target, true);
					tree.expandItem(target);

					Object itemId = tree.addItem();
					tree.setParent(itemId, target);
					tree.setChildrenAllowed(itemId, false);

					// Set the name for this item (we use it as item caption)
					Item item = tree.getItem(itemId);
					item.getItemProperty(TreePageModel.CAPTION).setValue(
							"New book");
					Leaf leaf = new Leaf("New book");

					model.createLeaf(leaf, node);
					item.getItemProperty(TreePageModel.TREE_PAGE_MODEL)
							.setValue(leaf);

				} else if (targetObject instanceof String) {
					tree.setChildrenAllowed(target, true);
					tree.expandItem(target);

					// Create new item, set parent, disallow children (= leaf
					// node)
					Object itemId = tree.addItem();
					tree.setParent(itemId, target);
					tree.setChildrenAllowed(itemId, true);

					// Set the name for this item (we use it as item caption)
					Item item = tree.getItem(itemId);
					item.getItemProperty(TreePageModel.CAPTION).setValue(
							"New directory");
					Node node = new Node("New directory");
					model.createNode(node);
					item.getItemProperty(TreePageModel.TREE_PAGE_MODEL)
							.setValue(node);

				}

			} else if (action == ACTION_DELETE && target != null) {

				Object targetObject = tree.getContainerProperty(target,
						TreePageModel.TREE_PAGE_MODEL).getValue();

				tree.removeItem(target);

				if (targetObject instanceof Node) {

					model.deleteNode((Node) targetObject);
					initData();

				} else if (targetObject instanceof Leaf) {
					model.deleteLeaf((Leaf) targetObject);
				}
				tree.requestRepaint();
			}

		}

	}

	private class TreeItemClickListener implements ItemClickListener {

		public void itemClick(ItemClickEvent event) {

			switch (event.getButton()) {
			case ItemClickEvent.BUTTON_LEFT:

				LOGGER.debug("Tree item clicked");

				Object clicketItem = event.getItem().getItemProperty(
						TreePageModel.TREE_PAGE_MODEL).getValue();
				LOGGER.debug("Object class " + clicketItem.toString());
				if (clicketItem instanceof Leaf) {
					LOGGER.debug("Object is leaf");
					Leaf leaf = (Leaf) event.getItem().getItemProperty(
							TreePageModel.TREE_PAGE_MODEL).getValue();
					view.getInfoPanel().setLeaf(leaf);
					LOGGER.debug("The leaf description: "
							+ leaf.getDescriptionLabel());
					if (leaf.getDescriptionLabel() != null) {
						view.getInfoPanel().getRichText().setValue(
								leaf.getDescriptionLabel());
					} else {
						view.getInfoPanel().getRichText().setValue("");
					}

					view.getInfoPanel().getHeaderText()
							.setValue(leaf.getName());

					/*
					 * view.openPdfViewer();
					 * 
					 * view.addSearchContent(new ArrayList<Integer>());
					 * view.getSearchText().setValue("");
					 * 
					 * currentZoom = Zoom.ZOOM_100; currentPage = 1; serched =
					 * Collections.emptyList(); currentFileName =
					 * LuceneRepository.getRepositoryPath() + event.getItemId();
					 * view.displayPdf(model.createPage(currentFileName,
					 * currentZoom, currentPage));
					 * view.getAllPages().setCaption("/" + model.getAllPages());
					 * view.getPages().setValue(currentPage);
					 * view.getZoomLabel().setCaption(currentZoom.toString());
					 */
				}

				break;
			case ItemClickEvent.BUTTON_MIDDLE:

				break;
			case ItemClickEvent.BUTTON_RIGHT:

				break;
			}

		}

	}

	private class InfoPanelEditButtonListener implements ClickListener {

		public void buttonClick(ClickEvent event) {

			LOGGER.debug("Button clicked " + event.getButton().getCaption());

			final InfoLayout infoPanel = view.getInfoPanel();

			if (event.getButton().getCaption().equals("Edit")) {
				view.getEditor().setValue(infoPanel.getRichText().getValue());
				infoPanel.replaceComponent(infoPanel.getRichText(), view
						.getEditor());
				infoPanel.getEditButton().setCaption("Apply");
			} else {

				infoPanel.getRichText().setValue(view.getEditor().getValue());
				infoPanel.replaceComponent(view.getEditor(), infoPanel
						.getRichText());
				infoPanel.getEditButton().setCaption("Edit");
				Leaf leaf = infoPanel.getLeaf();
				leaf
						.setDescriptionLabel(view.getEditor().getValue()
								.toString());

				model.updateLeaf(leaf);
			}

		}
	}

}
